package cn.net.isir.controller.manager;

import cn.net.isir.common.CacheManager;
import cn.net.isir.common.ResultObject;
import cn.net.isir.common.TokenManager;
import cn.net.isir.core.ShiroUsernamePasswordPhoneToken;
import cn.net.isir.entity.Permission;
import cn.net.isir.entity.User;
import cn.net.isir.entity.UserInfo;
import cn.net.isir.entity.dto.LoginUser;
import cn.net.isir.service.*;
import cn.net.isir.utils.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.subject.Subject;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.*;

/**
 * @author liuxubo
 * @filename LoginController.java
 * @package cn.net.isir.controller.manager
 * @email lxb@isir.net.cn
 * @date 2018/11/20
 * @comment
 * @since 1.8
 */
@RestController
@RequestMapping("/manage")
public class ManageController {
    // 声明log4j日志
    private static org.apache.log4j.Logger logger = org.apache.log4j.Logger.getLogger(ManageController.class);

    @Resource
    private UserInfoService userInfoService;
    @Resource
    private UserService userService;
    @Resource
    private UserRoleService userRoleService;
    @Resource
    private RolePermissionService rolePermissionService;
    @Resource
    private PermissionService permissionService;

    /**
     * 判断当前用户是否已登录
     *
     * @return 登录状态
     */
    @RequestMapping(value = "/isLogged", method = RequestMethod.GET)
    public ResultObject isLogged() {
        logger.info("getPrincipal:" + SecurityUtils.getSubject().getPrincipal());
        logger.info("isAuthenticated:" + SecurityUtils.getSubject().isAuthenticated());
        logger.info("getSession:" + SecurityUtils.getSubject().getSession());
        logger.info("isRemembered:" + SecurityUtils.getSubject().isRemembered());
//        alipay.open.servicemarket.order.notify
        return new ResultObject(200, "success",
                SecurityUtils.getSubject().getPrincipal() != null);
    }

    /**
     * 获取当前登陆用户的信息
     *
     * @return 用户信息
     */
    @RequestMapping(value = "/info", method = RequestMethod.GET)
    public ResultObject getInfo() {
        if (StringUtils.isBlank(TokenManager.getTokenId())) {
            return new ResultObject(500, "need login.", null);
        }
        return new ResultObject(200, "success", userInfoService.selectByUserId(TokenManager.getTokenId()));
    }

    /**
     * 使用手机号登陆
     *
     * @param loginUser 参数列表
     * @return 请求结果
     */
    @RequestMapping(value = "/login", method = RequestMethod.POST)
    public Map login(@RequestBody LoginUser loginUser) {

        Map<String, Object> map = new HashMap<>();
        try {
            //尝试登陆
//            UsernamePasswordToken upToken = new UsernamePasswordToken(loginUser.getUserName(), loginUser.getPassword());
            ShiroUsernamePasswordPhoneToken phoneToken = new ShiroUsernamePasswordPhoneToken(loginUser.getUserName(), loginUser.getPassword());
            //如果选择了自动登录,则remember me
            phoneToken.setRememberMe(loginUser.isAutoLogin());
            //尝试登陆
            SecurityUtils.getSubject().login(phoneToken);
        } catch (UnknownAccountException ex) {
            ex.printStackTrace();
            map.put("status", "fail");
            map.put("type", "account");
            map.put("currentAuthority", "guest");
            map.put("message", "用户不存在");
            return map;
        } catch (IncorrectCredentialsException ex) {
            ex.printStackTrace();
            map.put("status", "fail");
            map.put("type", "account");
            map.put("currentAuthority", "guest");
            map.put("message", "用户名或密码不匹配");
            return map;
        } catch (LockedAccountException ex) {
            ex.printStackTrace();
            map.put("status", "fail");
            map.put("type", "account");
            map.put("currentAuthority", "guest");
            map.put("message", "账户已锁定");
            return map;
        } catch (DisabledAccountException ex) {
            ex.printStackTrace();
            map.put("status", "fail");
            map.put("type", "account");
            map.put("currentAuthority", "guest");
            map.put("message", "账户已失效");
            return map;
        } catch (AuthenticationException ex) {
            ex.printStackTrace();
            map.put("status", "fail");
            map.put("type", "account");
            map.put("currentAuthority", "guest");
            map.put("message", "其他错误");
            return map;
        }
//        logger.info(subject.getPrincipal());
//        String userName = (String) subject.getPrincipal();

        map.put("status", "ok");
        map.put("type", "account");
        // 权限set
        Set<String> permissionStr = new HashSet<>();
        permissionStr.add("login");// 增加登陆的默认权限
        // 查询当前用户拥有的权限
        User user = new User();
        user.setId(TokenManager.getTokenId());
        List<Permission> permissionList = permissionService.selectPermissionListByUserId(user);
        permissionList.forEach(item -> permissionStr.add(item.getPermissionValue()));
        map.put("currentAuthority", permissionStr.toArray());
        return map;
    }

    /**
     * 使用手机号登陆
     *
     * @param loginUser 参数列表
     * @return 请求结果
     */
    @RequestMapping(value = "/loginByPhone", method = RequestMethod.POST)
    public Map loginByPhone(@RequestBody LoginUser loginUser) {
        Map<String, Object> map = new HashMap<>();

        String phone = loginUser.getMobile();
        if (StringUtils.isBlank(phone)) {
            map.put("status", "mobile is blank");
            map.put("result", "101");
            map.put("type", "account");
            map.put("currentAuthority", "guest");
            return map;
        }
        String verCode = loginUser.getVerificationCode();
        if (StringUtils.isBlank(verCode)) {
            map.put("status", "verCode is blank");
            map.put("result", "101");
            map.put("type", "account");
            map.put("currentAuthority", "guest");
            return map;
        }
        String cacheVerCode = CacheManager.getVerCode(loginUser.getMobile(), "login");
        if (!verCode.equals(cacheVerCode)) {
            map.put("status", "verCode is not match.");
            map.put("result", "403");
            map.put("type", "account");
            map.put("currentAuthority", "guest");
            return map;
        }
        try {
            ShiroUsernamePasswordPhoneToken phoneToken = new ShiroUsernamePasswordPhoneToken(phone);
            phoneToken.setRememberMe(false);
            SecurityUtils.getSubject().login(phoneToken);
            //删除手机号验证码
            CacheManager.deleteVerCode(loginUser.getMobile(), "login");
        } catch (Exception ex) {
            map.put("status", "loginError");
            map.put("result", "500");
            map.put("type", "account");
            map.put("currentAuthority", "guest");
            return map;
        }
        map.put("status", "ok");
        map.put("result", "200");
        map.put("type", "account");
        // 权限set
        Set<String> permissionStr = new HashSet<>();
        permissionStr.add("login");// 增加登陆的默认权限
        // 查询当前用户拥有的权限
        User user = new User();
        user.setId(TokenManager.getTokenId());
        List<Permission> permissionList = permissionService.selectPermissionListByUserId(user);
        permissionList.forEach(item -> permissionStr.add(item.getPermissionValue()));
        map.put("currentAuthority", permissionStr.toArray());
        return map;
    }

    /**
     * 使用手机号登陆
     *
     * @return 请求结果
     */
    @RequestMapping(value = "/loginByPhoneGet", method = RequestMethod.GET)
    public Map loginByPhoneGet(HttpServletRequest request) {
        String phone = request.getParameter("mobile");
        if (StringUtils.isNotBlank(phone)) {
            ShiroUsernamePasswordPhoneToken phoneToken = new ShiroUsernamePasswordPhoneToken(phone);
            phoneToken.setRememberMe(true);
            SecurityUtils.getSubject().login(phoneToken);
        }
        logger.info(SecurityUtils.getSubject().isAuthenticated());
        return null;
    }

    /**
     * 重置密码
     *
     * @return 请求结果
     */
    @RequestMapping(value = "/resetPwd", method = RequestMethod.POST)
    public ResultObject resetPwd(@RequestBody LoginUser loginUser) {
        //验证码不匹配
        if (!loginUser.getVerificationCode().equals(
                CacheManager.getVerCode(loginUser.getMobile(), "reset"))) {
            return new ResultObject(513, "fail", "verCodeErr");
        }
        UserInfo userInfo = new UserInfo();
        userInfo.setTel(loginUser.getMobile());
        userInfo = userInfoService.selectOne(userInfo);
        User user = userService.selectByPrimaryKey(userInfo.getUserId());
        user.setPassword(loginUser.getPassword());
        TokenManager.editUser(user, null);
        //删除手机号验证码
        CacheManager.deleteVerCode(loginUser.getMobile(), "reset");
        return new ResultObject(200, "success", loginUser.getMobile());
    }

    /**
     * 使用手机号登陆-get
     *
     * @param request  请求
     * @param response 返回值
     * @return 请求结果
     */
    @RequestMapping(value = "/loginGet", method = RequestMethod.GET)
    public Map loginGet(HttpServletRequest request, HttpServletResponse response) {
        logger.info(request.getParameter("ticket"));
//        //声明返回值
        ResultObject ro = new ResultObject();
        String user = request.getParameter("u");
        String pwd = request.getParameter("p");
//        pwd = new Md5Hash(pwd, user).toHex();
//        pwd = new SimpleHash("md5", pwd, user).toHex();

        Subject subject = SecurityUtils.getSubject();
        UsernamePasswordToken token = new UsernamePasswordToken(user, pwd);
        try {
            subject.login(token);
        } catch (AuthenticationException ex) {
            ex.printStackTrace();
            logger.info(ex.getMessage());
            ro.setResult(response, 500);
            ro.setMessage(ex.getMessage());
            return null;
        }
        logger.info(subject.getPrincipal());
        String userName = (String) subject.getPrincipal();

        ro = new ResultObject();
        ro.setResult(200);
        response.setStatus(200);
        ro.setMessage("登陆成功！");

        Map<String, String> map = new HashMap<>();
        map.put("status", "ok");
        map.put("type", "account");
        map.put("currentAuthority", userName);
        return map;
    }

    /**
     * 登出
     *
     * @return 请求结果
     */
    @RequestMapping(value = "/logout")
    public Map logout() {
        Subject subject = SecurityUtils.getSubject();
        try {
            subject.logout();
        } catch (AuthenticationException ex) {
            ex.printStackTrace();
            logger.info(ex.getMessage());
            return null;
        }

        Map<String, String> map = new HashMap<>();
        map.put("status", "ok");
        map.put("type", "account");
        map.put("currentAuthority", null);
        return map;
    }

    /**
     * 注册用户
     *
     * @param loginUser 注册用户
     * @return 结果
     */
    @RequestMapping(value = "/register", method = RequestMethod.POST)
    public Map register(@RequestBody LoginUser loginUser) {
        Map<String, Object> map = new HashMap<>();
        //验证码不匹配
        if (!loginUser.getVerificationCode().equals(
                CacheManager.getVerCode(loginUser.getMobile(), "register"))) {
            map.put("status", "verCodeErr");
            map.put("currentAuthority", "guest");
            return map;
        }
        User user = new User();
        user.setUsername(loginUser.getUserName());
        user.setPassword(loginUser.getPassword());
        user.setUserType("business");
        UserInfo userInfo = new UserInfo();
        userInfo.setTel(loginUser.getMobile());
        int count = userInfoService.selectCount(userInfo);
        //如果该手机号已经注册了，返回已注册
        if (count > 0) {
            //用户已存在
            map.put("status", "exist");
            map.put("currentAuthority", "guest");
            return map;
        }

        ResultObject ro = TokenManager.register(user, userInfo);
        //用户已存在
        if (ro.getResult() == 103) {
            map.put("status", "exist");
            map.put("currentAuthority", "guest");
            return map;
        }
        //注册不成功
        if (ro.getResult() != 100) {
            //其他错误
            map.put("status", "error");
            map.put("currentAuthority", "guest");
            return map;
        }
        //注册成功
        map.put("status", "ok");
        map.put("currentAuthority", "user");
        //删除手机号验证码
        CacheManager.deleteVerCode(loginUser.getMobile(), "register");
        return map;
    }
}
